using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace COME342.CollisionResolution.BinaryTree
{
    public partial class frmAVLTree : Form
    {
        private AVLTree<string> sTreeOrig;
        private AVLTree<string> shownTree;

        bool fastAdd = false;
        bool cl = false;

        string key2 = "", key3 = "", key1 ="";

        public frmAVLTree(AVLTree<string> avl)
        {
            InitializeComponent();
            sTreeOrig = avl;
            AVLTree<string>.PreRotation += new AVLTree<string>.PreRotationHandler(avl_PreRotation);
            UpdateTree(avl);
        }

        void HighlightKeys(bool light)
        {
            treeExControl1.Highlight(key2, light);
            treeExControl1.Highlight(key3, light);
            treeExControl1.Highlight(key1, light); 
        }

        void avl_PreRotation(AVLTree<string> tree, string data, AVLTree<string>.RotationType rot)
        {
            UpdateTree(sTreeOrig);            

            AVLTree<string> sub = tree.FindNode(data);
            switch (rot)
            {
                case AVLTree<string>.RotationType.LL:
                    key2 = sub.left.data;
                    key3 = sub.left.left.data;
                    break;
                case AVLTree<string>.RotationType.LR:
                    key2 = sub.left.data;
                    key3 = sub.left.right.data;
                    break;
                case AVLTree<string>.RotationType.RL:
                    key2 = sub.right.data;
                    key3 = sub.right.left.data;
                    break;
                case AVLTree<string>.RotationType.RR:
                    key2 = sub.right.data;
                    key3 = sub.right.right.data;
                    break;
            }
            key1 = data;
            HighlightKeys(true);

            lblRot.Text = rot.ToString() + " on " + data;            
            if (!fastAdd)
            {
                lblRot.ForeColor = Color.LightGray;
                Application.DoEvents();
                System.Threading.Thread.Sleep((int)nuDelay.Value);
                UpdateTree(sTreeOrig);
                lblRot.ForeColor = Color.Gray;
            }

        }

        public void UpdateTree(AVLTree<string> avl)
        {
            shownTree = avl.Copy();            
            TreeEx.NodeEx root;
            InitTree(out root, shownTree);
            treeExControl1.Root = root;
            treeExControl1.HighlightAll(false);
            treeExControl1.Invalidate();
        }

        private void InitTree(out TreeEx.NodeEx root, AVLTree<string> avl)
        {
            TreeEx.NodeEx ne = new TreeEx.NodeEx(avl.data.ToString(), avl.ToString());
            ne.Highlight(!avl.IsBalanced);
            if (!avl.IsLeftEmpty())
                FillTree(ref ne, avl.left);
            if (!avl.IsRightEmpty())
                FillTree(ref ne, avl.right);
            root = ne;
        }

        private void FillTree(ref TreeEx.NodeEx ret, AVLTree<string> avl)
        {
            TreeEx.NodeEx ne = new TreeEx.NodeEx(avl.data.ToString(), avl.ToString());
            ne.Highlight(!avl.IsBalanced);
            ret.Add(ne);
            if (!avl.IsLeftEmpty())
                FillTree(ref ne, avl.left);
            if (!avl.IsRightEmpty())
                FillTree(ref ne, avl.right);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            txtItem.Enabled = false;
            sTreeOrig.Insert(txtItem.Text);
            UpdateTree(sTreeOrig);
            HighlightKeys(true);
            txtItem.Enabled = true;
            txtItem.Focus();
            txtItem.SelectAll();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            sTreeOrig.left = null;
            sTreeOrig.right = null;
            sTreeOrig.data = txtItem.Text;
            UpdateTree(sTreeOrig);
        }

        private void btnAddRange_Click(object sender, EventArgs e)
        {
            int i = (int)numericUpDown1.Value;
            
            Random x = new Random();
            while (i-- != 0)
            {
                fastAdd = !chkSlow.Checked;
                sTreeOrig.Insert(util.RandomString(7, x.Next(), true));
                //Console.WriteLine(i.ToString() +" "+ util.RandomString(7, x.Next(), true));
            }

            fastAdd = false;

            UpdateTree(sTreeOrig);
            HighlightKeys(true);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            cl = true;
            this.Close();
        }

        private void frmAVLTree_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = !cl;
        }

    }
}